package com.example.demospringboot.batch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepExecutionListener;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.validator.Validator;
import org.springframework.batch.support.DatabaseType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;
import com.example.demospringboot.batch.processor.BeanItemProcesser;
import com.example.demospringboot.batch.reader.MyItemReader;
import com.example.demospringboot.entity.User;

@Configuration
@EnableBatchProcessing
public class BatchConfig {
	
	/**
	 * 读取器
	 * @return
	 */
	@Bean
	public ItemReader<User> reader(DruidDataSource datasource){
		return new MyItemReader(datasource);
	}
	
	/**
	 * 处理器并设置校验器
	 * @return
	 */
	@Bean
	public ItemProcessor<User, User> processor(){
		BeanItemProcesser processor = new BeanItemProcesser();
		processor.setValidator(validator());
		return processor;
	}
	
	/**
	 * 校验器
	 * @return
	 */
	@Bean
	public Validator<User> validator(){
		return new BeanValidator<>();
	}
	
	/**
	 * 写入器
	 * @param dataSource
	 * @return
	 */
	@Bean
	public ItemWriter<User> writer(DruidDataSource dataSource){
		JdbcBatchItemWriter<User> writer = new JdbcBatchItemWriter<>();
		writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>());
		String sql = "insert into tb_user (guid,user_name,password,type) values(:guid,:userName,:password,:type)";
		writer.setSql(sql);
		writer.setDataSource(dataSource);
		return writer;
	}
	
	@Bean
	public JobRepository jobRepository(DruidDataSource dataSource,PlatformTransactionManager transactionManager) throws Exception {
		JobRepositoryFactoryBean bean = new JobRepositoryFactoryBean();
		bean.setDataSource(dataSource);
		bean.setTransactionManager(transactionManager);
		bean.setDatabaseType(String.valueOf(DatabaseType.MYSQL));
		bean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
		bean.afterPropertiesSet();
		return bean.getObject();
	}
	
	@Bean
    public SimpleJobLauncher jobLauncher(DruidDataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository(dataSource, transactionManager));
        return jobLauncher;
    }
	
	@Bean
	public Job testJob(JobBuilderFactory jobBuilderFactory,Step step) {
		return jobBuilderFactory.get("testJob")
				.incrementer(new RunIdIncrementer())
				.flow(step)
				.end()
				.listener(myJobListener())
				.build();
	}
	
	@Bean
	public Step step(StepBuilderFactory stepBuilderFactory,ItemReader<User> reader,ItemWriter<User> writer,ItemProcessor<User, User> itemProcessor) {
		return stepBuilderFactory.get("step")
				.<User,User>chunk(1)
				.reader(reader)
				.processor(itemProcessor)
				.writer(writer)
				.listener(myStepListener())
				.build();
				
	
	}
	
	@Bean 
	public JobExecutionListener myJobListener() {
		return new MyJobListener();
	}
	
	@Bean
	public StepExecutionListener myStepListener() {
		return new MyStepExecutionListener();
	}
	
	
}
